﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows;
using Microsoft.Win32;

namespace TestRunner 
{
    [Serializable]
    public class LocalSettings
    {
        internal Dictionary<string, Tuple<HashSet<string>, HashSet<string>>> TestMap = new Dictionary<string, Tuple<HashSet<string>, HashSet<string>>>(StringComparer.OrdinalIgnoreCase);
        internal Uri PresentationThemeUsed { get; set; }
        internal string NUnitFolderPath { get; set; }
        internal bool NUnitIs32Bit { get; set; }
        internal int LastSelectedParallelThreads { get; set; }
        internal int LastSelectedRepeateCount { get; set; }
        internal List<string> LastUsedAssemblyPath { get; set; }
        static internal LocalSettings LoadSettings()
        {
            Stream userStream = null;
            try
            {
                IsolatedStorageFile userStore = IsolatedStorageFile.GetMachineStoreForAssembly();
                userStream = new IsolatedStorageFileStream("LocalSettings.settings", FileMode.OpenOrCreate, userStore);
                BinaryFormatter bf = new BinaryFormatter();
                var theObj = (LocalSettings) bf.Deserialize(userStream);
                theObj.NUnitFolderPath = theObj.NUnitFolderPath ?? GetNUnitPath();
                if (theObj.LastUsedAssemblyPath == null)
                {
                    theObj.LastUsedAssemblyPath = new List<string>();
                }
                return theObj;
            }
            catch (Exception)
            {
                //MessageBox.Show("Failed to Load settings.", "Test Runner", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                if(userStream != null) userStream.Dispose();
            }
            var newSetting = new LocalSettings();
            newSetting.NUnitFolderPath = newSetting.NUnitFolderPath ?? GetNUnitPath();
            newSetting.LastUsedAssemblyPath = new List<string>();
            return newSetting;
        }

        public void Save()
        {
            IsolatedStorageFileStream userStream = null;
            try
            {
                //lock (syncLock)
                {
                    IsolatedStorageFile userStore = IsolatedStorageFile.GetMachineStoreForAssembly();
                    userStream = new IsolatedStorageFileStream("LocalSettings.settings", FileMode.OpenOrCreate, userStore);
                    userStream.SetLength(0);
                    BinaryFormatter bf = new BinaryFormatter();
                    bf.Serialize(userStream, this);
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Failed to save settings.", "Test Runner", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                if (null != userStream) userStream.Close();
            }
        }

        public string GetNunitExecutablePath()
        {
            if (String.IsNullOrWhiteSpace(NUnitFolderPath)) return null;
            if (!Directory.Exists(NUnitFolderPath)) return null;
            string filePath = Path.Combine(NUnitFolderPath, NUnitIs32Bit ? "nunit-console-x86.exe" : "nunit-console.exe");
            if (!File.Exists(filePath)) return null;
            return filePath;
        }

        public static string GetNUnitPath()
        {
            const string nunitPath = @"Software\nunit.org\NUnit";
            RegistryKey key = Registry.CurrentUser;
            
            using (var nunitkey = key.OpenSubKey(nunitPath))
            {
                if (nunitkey != null)
                {
                    var versions = nunitkey.GetSubKeyNames();

                    var peferrredVersion = versions.FirstOrDefault(p => p == "2.6.1");
                    if (peferrredVersion != null)
                    {
                        using (var versionKey = nunitkey.OpenSubKey(peferrredVersion))
                        {
                            if (versionKey != null)
                            {
                                var path = versionKey.GetValue("InstallDir") as string;
                                if (!String.IsNullOrWhiteSpace(path))
                                {
                                    path = Path.Combine(path, "bin");
                                }
                                return path;
                            }
                        }
                    }
                    else
                    {
                        var versionPairs =versions.Select(p => new Tuple<Version, string>(new Version(p), p)) .OrderByDescending(p => p.Item1);
                        var highestVersion = versionPairs.First();

                        using (var versionKey = nunitkey.OpenSubKey(highestVersion.Item2))
                        {
                            if (versionKey != null)
                            {
                                var path = versionKey.GetValue("InstallDir") as string;
                                if (!String.IsNullOrWhiteSpace(path)) 
                                {
                                    path = Path.Combine(path, "bin");
                                }
                                return path;
                            }
                        }
                    }
                }
            }
            return null;
        }
    }
}
